package settingsapp.gestures;

import settingsapp.settings.continuous.ContinuousSettingFactory;
import settingsapp.settings.toggle.ToggleSettingFactory;
import settingsapp.ui.PanelGridActivity;
import ece.settingsapp.R;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.widget.ImageView;
import android.widget.Toast;


public class GestureHandler extends SimpleOnGestureListener
{
	public static final String TAG = GestureHandler.class.getSimpleName();
	
	private PanelGridActivity myActivity;
	private TargetGesture gestureBuffer;
	private GestureLibrary gestureLibrary;	
	
	public GestureHandler(PanelGridActivity activity, GestureLibrary lib)
	{
		super();
		myActivity = activity;
		gestureLibrary = lib;
		gestureBuffer = new TargetGesture();
	}	
		
	// Check if a particular MotionEvent occurred within the bounds of a target view
	private boolean checkWithinBounds(MotionEvent e1, View view)
	{
		float x = e1.getX();
		float y = e1.getY();		
				
		if(x > view.getLeft() && x < view.getRight())
			if(y > view.getTop() && y < view.getBottom())
			{		
				return true;				
			}
		return false;
	}
	
	// Remove the highlighting from all of the targets
	private void clearHighlights()
	{
		ImageView target = (ImageView)myActivity.findViewById(R.id.TargetViewTop); 
		target.setImageResource(R.drawable.target);
		target = (ImageView)myActivity.findViewById(R.id.TargetViewLeft);
		target.setImageResource(R.drawable.target);
		target = (ImageView)myActivity.findViewById(R.id.TargetViewRight);
		target.setImageResource(R.drawable.target);
		target = (ImageView)myActivity.findViewById(R.id.TargetViewBottom);     		
		target.setImageResource(R.drawable.target);
	}

	// Detect if any of the touch targets were hit by a motion event
	//  Return which one was hit as an int 0-3, 0=top, left, right, bottom.
	//  Returns -1 for no target touched
	public int detectTargetTouch(MotionEvent e1)
	{   		
		View topTarget = myActivity.findViewById(R.id.TargetViewTop); 
		View leftTarget = myActivity.findViewById(R.id.TargetViewLeft); 
		View rightTarget = myActivity.findViewById(R.id.TargetViewRight);
		View botTarget = myActivity.findViewById(R.id.TargetViewBottom); 
		
		int targetTouched;
		
		if(checkWithinBounds(e1, topTarget))
		{
			highlightTarget(0);
			targetTouched = 0;
		}
		else if(checkWithinBounds(e1, leftTarget))
		{
			highlightTarget(1);
			targetTouched = 1;
		}
		else if(checkWithinBounds(e1, rightTarget))
		{
			highlightTarget(2);
			targetTouched = 2;
		}
		else if(checkWithinBounds(e1, botTarget))
		{
			highlightTarget(3);
			targetTouched = 3;
		}
		else
			return -1; // No target touched
		
		gestureBuffer.addTargetTouch(targetTouched);
		
		// Return the touched target
		return targetTouched;
	}
	// End the gesture and attempt to recognize it
	private void endGesture()
	{
		int actionType, actionId;	
		boolean closingGesture;
				
		clearHighlights();
		gestureBuffer.endGesture();		
		
		TargetGesture gesture = gestureLibrary.identifyGesture(gestureBuffer);
		if(gesture == null) // If the base gesture was not found, check for an ending gesture that matches
			gesture = gestureLibrary.identifyTerminatingGesture(gestureBuffer);		
		
		// If this gesture was found, perform its associated action		
		if(gesture != null)
		{
			actionType = gesture.getActionType();
			actionId = gesture.getActionId();
			closingGesture = gestureBuffer.isActivityClosingGesture(); 
				
			if(myActivity.inConfigMode())
			{
				Toast.makeText(myActivity.getApplicationContext(), "Gesture recognized, but suppressed (Config. Mode).", Toast.LENGTH_SHORT).show();
			}
			else
			{
				Toast.makeText(myActivity.getApplicationContext(), "Gesture recognized!", Toast.LENGTH_SHORT).show();
				myActivity.gestureActionPerformed(actionType, actionId, closingGesture);				
			}
		}			
		else
			Toast.makeText(myActivity.getApplicationContext(), "Gesture not recognized", Toast.LENGTH_SHORT).show();
	}
	
	private void highlightTarget(int targetNum)
	{
		ImageView target;
		
		switch(targetNum)
		{
		case 0: {
			target = (ImageView)myActivity.findViewById(R.id.TargetViewTop);
			target.setImageResource(R.drawable.target_hit);
			break;
			}
		case 1: {
			target = (ImageView)myActivity.findViewById(R.id.TargetViewLeft);
			target.setImageResource(R.drawable.target_hit);
			break;
			}    			
		case 2: {
			target = (ImageView)myActivity.findViewById(R.id.TargetViewRight);
			target.setImageResource(R.drawable.target_hit);
			break;
			}    			
		case 3: {
			target = (ImageView)myActivity.findViewById(R.id.TargetViewBottom);
			target.setImageResource(R.drawable.target_hit);
			break;
			}    			
		default: break;   		
		}
	}
		
	// Initial touch down
	public boolean onDown(MotionEvent e1)
	{
		// Prepare for a new gesture
		gestureBuffer.clear();
		
		// Detect if one of the 'targets/nodes' was touched by this
		if(detectTargetTouch(e1) != -1)		
		{
			
			return true; // Handled			
		}		
		return false;
	}
	
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
	{
		detectTargetTouch(e2);
		endGesture();
		return true;
	}
	
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
	{
		detectTargetTouch(e2);   		
		return true;
	}
	
	public boolean onUp(MotionEvent e1)
	{
		endGesture();
		return true;
	}
		
	public void saveLastGesture()
	{
		showSetTypeDialog();
	}
	
	public void saveLastGesture(int actionType, int actionId)
	{
		if(gestureBuffer.isActivityClosingGesture())
			Toast.makeText(myActivity.getApplicationContext(), "Note: Gestures that terminate on the bottom node are quick-end gestures, they will close the app after performing their function.", Toast.LENGTH_LONG).show();
		gestureLibrary.addGesture(new TargetGesture(gestureBuffer, actionType, actionId), true);
	}
	
	public void showSetTypeDialog()
	{
		final CharSequence[] items = {"Toggle Setting", "Continuous Setting"};
		
		// display a dialog to select a new setting type for this gesture
		AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
		builder.setTitle("Choose a setting type");
		builder.setItems(items, new DialogInterface.OnClickListener()
		{
		    public void onClick(DialogInterface dialog, int item)
		    {
		    	switch (item)
		    	{
		    	case 0:
		    		showSetTypeSubDialogToggle();
		    		break;
		    	case 1:
		    		showSetTypeSubDialogContinuous();
		    		break;
		    	}
		    }
		});
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	private void showSetTypeSubDialogToggle()
	{
		final CharSequence[] items = ToggleSettingFactory.getSettingTypes();		// retrieve the names of the different possibilities
		
		// display a dialog to select a new setting type for this gesture
		AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
		builder.setTitle("Choose a setting");
		builder.setItems(items, new DialogInterface.OnClickListener()
		{
		    public void onClick(DialogInterface dialog, int item)
		    {
		    	saveLastGesture(0, item);
		    }
		});
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	private void showSetTypeSubDialogContinuous()
	{
		final CharSequence[] items = ContinuousSettingFactory.getSettingTypes();		// retrieve the names of the different possibilities
		
		// display a dialog to select a new setting type for this gesture
		AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
		builder.setTitle("Choose a setting");
		builder.setItems(items, new DialogInterface.OnClickListener()
		{
			public void onClick(DialogInterface dialog, int item)
			{
				saveLastGesture(1, item);
			}
		});
		AlertDialog alert = builder.create();
		alert.show();
	}
}